package com.mytrip.util;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Calendar;
import java.util.Date;
import java.util.ResourceBundle;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.danga.MemCached.MemCachedClient;
import com.danga.MemCached.SockIOPool;

public class MemcachedProxy{

	private static String CURRENTVERSION = "";

	protected static Log sysLogger = LogFactory.getLog("sysLogger");

	private static MemcachedProxy instance;

	private static final int defaultExpiryMinutes = 60 * 12;

	private static final int SocketTimeout = 1000 * 3;

	private static final int socketConnectTO = 1000 * 3;

	private static final int initConn = 50;

	private static final int mainSleep = 30 * 1000;

	private static final int minConn = 50;

	private static final int maxConn = 500;

	private static final String poolname = "session";

	private static MemCachedClient MC = null;

	public static MemcachedProxy getInstance(){
		return instance;
	}

	/*
	 * 获得当前程序编译前的代码版本号 codeversion.properties 文件
	 */
	public static String getCurrentversion(String oldkey){
		// 如果 MemcachedProxy.CURRENTVERSION 不存在,去数据库读取 currentversion
		if ("".equals(MemcachedProxy.CURRENTVERSION)) {
			// 如果 MemcachedProxy.CURRENTVERSION 读取失败则不再读取,真接返回oldkey
			if (!"-1".equals(MemcachedProxy.CURRENTVERSION)) {
				try {
					ResourceBundle rm = ResourceBundle.getBundle("codeversion");
					String currentversionStr = rm.getString("currentversion");
					if (currentversionStr != null) {
						return CURRENTVERSION = currentversionStr;
					} else {
						MemcachedProxy.CURRENTVERSION = "-1";
					}
				} catch (Exception ex) {
					sysLogger.error("get currenversion key have some error || " + ex.getMessage());
					MemcachedProxy.CURRENTVERSION = "-1";
				}

				return oldkey;
			}
		}
		return MemcachedProxy.CURRENTVERSION;

	}

	public static String getGoodKey(String oldkey){
		int bylength = 0;

		StringBuffer sb = new StringBuffer(oldkey);
		String encodekey = "";
		try {
			oldkey = sb.append("_").append(MemcachedProxy.getCurrentversion(oldkey)).toString();
			encodekey = URLEncoder.encode(oldkey, "UTF-8");
			// oldkey 变为 oldkey+"_"+codeversion
		} catch (Exception e1) {
			try {
				encodekey = URLEncoder.encode(oldkey, "UTF-8");
			} catch (UnsupportedEncodingException e) {
				encodekey = oldkey;
				sysLogger.error("old key can't covent to utf-8 || " + e.getMessage());
			}
		}

		try {
			bylength = encodekey.length();

			if (bylength > 240 || oldkey.indexOf(" ") > -1) {
				// 经测试memcached最大支持250位key
				sysLogger.debug("this key is too long or have space :" + oldkey + "||  MD5 to 32 bit length!!");
				String headkey = null;
				if (encodekey.length() >= 48) {
					headkey = encodekey.substring(0, 48);
				} else {
					headkey = encodekey;
				}
				return headkey + "_" + MD5Support.MD5(oldkey) + "_" + MemcachedProxy.getCurrentversion(oldkey);
			} else
				return oldkey;

		} catch (Exception e) {
			e.printStackTrace();
			return oldkey;

		}

	}

	public void init(){
		String servers = Constant.getCommonConf("memcacheds");

		String[] serverlist = servers.split(",");
		SockIOPool pool = SockIOPool.getInstance(poolname);
		pool.setServers(serverlist);
		pool.setInitConn(initConn);
		pool.setMinConn(minConn);
		pool.setMaxConn(maxConn);
		pool.setMaintSleep(mainSleep);
		pool.setNagle(false);
		pool.setFailover(true);
		pool.setSocketTO(SocketTimeout);
		pool.setSocketConnectTO(socketConnectTO);

		pool.setHashingAlg(SockIOPool.CONSISTENT_HASH);

		// pool.setAliveCheck( true );
		// pool.setFailback(true);
		pool.initialize();
		for (int i = 0; i < serverlist.length; i++) {
			sysLogger.debug(" memcache server " + i + serverlist[i]);
		}

		MC = new MemCachedClient(poolname);

		instance = this;
	}

	public void close(){
		SockIOPool pool = SockIOPool.getInstance(poolname);
		pool.getMaxBusy();
		pool.shutDown();
	}

	public Object get(String key){
		sysLogger.info("MemCached is start");

		Object result = (Object) CacheInRequest.getResult(key);

		if (result != null) {

			return result;

		}
		MemCachedClient mc = MC;
		// mc.setPoolName(poolname);
		mc.setCompressEnable(true);
		Object obj = mc.get(MemcachedProxy.getGoodKey(key));
		sysLogger.info("MemCached is end");
		// sysLogger.info("Try get an object from memcached with key : " + key
		// + ", got object: " + obj);
		return obj;
	}

	/**
	 * 姒涙顓绘潻鍥ㄦ埂閺冨爼妫挎稉杞扮婢讹拷
	 * 
	 * @param key
	 * @param value
	 */
	public void put(String key, Object value){
		this.put(key, value, defaultExpiryMinutes);
	}

	public void put(String key, Object value, int expirMins){
		if (value != null) {
			MemCachedClient mc = MC;
			// mc.setPoolName(poolname);
			mc.setCompressEnable(true);
			CacheInRequest.setResult(key, value);
			if (expirMins > 0)
				// mc.set(key, value, getDateAfter(expirMins));
				mc.set(MemcachedProxy.getGoodKey(key), value, new Date(1000 * 60 * expirMins));
			else
				// mc.set(getGoodKey(key), value);
				// -------闄愭湡閿欒锛屽己鍒�0鍒嗗け鏁�--------------
				mc.set(MemcachedProxy.getGoodKey(key), value, new Date(1000 * 60 * 30));
		} else {
			try {
				throw new Exception("Memcache value is null error! The key is :" + key);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	public void remove(String key){
		MemCachedClient mc = MC;
		// mc.setPoolName(poolname);
		mc.delete(MemcachedProxy.getGoodKey(key));
	}

	public Date getDateAfter(int mins){
		Calendar cal = Calendar.getInstance();
		cal.add(Calendar.MINUTE, mins);
		return cal.getTime();
	}

}
